<template>
    <TransitionGroup name="drag" tag="ul" class="el-upload-list--picture-card">
        <li v-for="(item, index) in upfiles" :key="item.id||index" :class="['el-upload-list__item',{editli:isEdit==index},{active:options.active==index}]" @dragenter="dragList.dragenter($event, index, upfiles)" @dragstart="dragList.dragstart(index)" @dragover="dragList.dragover($event)"
        :style="{width: (options.width||140)+'px', height: (options.height||140)+'px'}">
            <div draggable="true" :class="['drag-move', {file:options.other}]" style="width: 100%">
                <el-image v-if="isImageUrl(item.url)" :fit="options.fit" class="img-item" :src="item.url" :preview-src-list="piclist" :initial-index="index" />
                <svg v-else height="30" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><path d="M131.71,12.54h-104V187.41h145V50.1ZM158.56,174H41.85V26H120V62.67h38.56Z" fill="#819292"/><path d="M58.85,81.73h85.47V94.84H58.85Zm0,31.26h43v13.1h-43Zm0,31.25h27v13.1h-27Z" fill="#819292"/><circle cx="135.22" cy="153.23" r="37.54" fill="#50a135"/><path d="M154.69,135.05l-25.43,24.12-13.51-12.81-7.52,7.13,13.51,12.81-.18.17,7.52,7.13,33.12-31.42Z" fill="#fff"/></svg>
                <h3>{{ item.name||'' }}</h3>
            </div>
            <div class="uploadbtn">
                <el-popconfirm title="确定删除此图片?" icon-color="red" @confirm="dragRemove(index)" v-if="!disabled&&!options.noClose">
                    <template #reference>
                        <div class="btn" title="删除">×</div>
                    </template>
                </el-popconfirm>
                <div class="btn editbtn" @click="onEdit(index)" title="重新上传" v-if="!disabled">
                    <span v-if="isEdit==index">取消修改</span>
                    <svg v-else xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><path d="M20.5,63.2V178.8H179.4V63.2H165V164.4H35V63.2Zm79.5-42L67.5,56H92.8v72.3h14.5V56h25.3Z" fill="#fff"/></svg>
                </div>
                <slot :evItem="item">
                    <!-- <div class="upload-copy" @click="copyUrl(index, upfiles)" title="复制图片地址">Copy</div> -->
                    <div class="btn" @mousedown="editorImg(index, upfiles)" title="插入到内容编辑器" v-if="!disabled">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><polygon points="12 12 12 24.78 175.2 24.8 175.2 175.2 24.8 175.2 24.8 131.24 12 131.24 12 188 188 188 188 12 12 12" fill="#fff"/><polygon points="78.86 105.64 87.89 114.68 114.73 87.84 123.81 78.8 114.73 69.72 88.66 43.64 79.58 52.68 99.66 72.76 12 72.76 12 85.56 98.94 85.56 78.86 105.64" fill="#fff"/></svg>
                    </div>
                </slot>
            </div>
        </li>

        <!-- 上传器图片 -->
        <el-upload ref="upload" key="001" name="file" :action="action" :headers='headers' :data="formdata" method="post" v-model="upfiles" :limit="maxnum" :accept="mime" list-type="picture" :show-file-list="false" multiple drag :auto-upload="autoupload" :on-remove="handleRemove" :on-exceed="(files, fileList)=>handleExceed(files, fileList, maxnum)" :before-upload="(file)=>handleBefore(file, upfiles, maxsize, maxnum)" :on-preview="handlePictureCardPreview" :on-success="(response, file, fileList)=>handleUpSuccess(response, file, fileList, upfiles)" :on-error="handleError" v-show="(!upfiles || upfiles.length < maxnum) && !disabled && !options.upDisable && !options.online" :on-change="handleChange" class="uploader">
            <div :style="[{height: options.height+'px'},'display:flex;align-items: center;']">
                <i class="el-icon-upload"></i>
                <div v-if="isEdit>-1" class="el-upload__text">修改第 {{isEdit+1}}张图...</div>
                <div v-else class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
                <div ref="onUpload" style="display: none"></div>
            </div>
        </el-upload>

        <div v-if="options.online && !options.upDisable && (!upfiles || upfiles.length < maxnum)" class="xuanbtn" @click="fileDialog = true">
            <div v-if="isEdit>-1">修改第 {{isEdit+1}}张图...</div>
            <div>选择在线{{options.other?'文件':'图片'}}</div>
        </div>

    </TransitionGroup>

    <el-dialog v-model="fileDialog" width="980" @close="isEdit=-1" title="选择在线文件">
        <slot name="filepopup" :isEdit="isEdit" :mime="mime" :maxsize="maxsize" :maxnum="maxnum" :upfiles="upfiles" :fileDialog="fileDialog" :closeDialog="closeDialog">
            <ul :class="['xuanlist', options.other?'list-style':'thumbnail-style']">
                <li v-for="(item, index) in material" :key="index" @click="onSelect(item, $event)">
                    <div class="img"><img :src="item.url" /></div>
                    <h4>{{ item.name||item.fileName }}</h4>
                    <span>{{ item.size }} kb</span>
                </li>
            </ul>
            <div class="dialog-footer">
                <el-button type="primary" v-if="options.sendEdit" @click="options.sendEdit(isEdit, upfiles)">素材中心</el-button>
                <!-- <el-button type="primary" plain @click="onUpload.click()">上传图片</el-button> -->
                <el-button @click="fileDialog = false">关闭</el-button>
            </div>
        </slot>
    </el-dialog>

</template>

<script setup>
/**
 * 图片上传组件
 * author: flashme.cn
 * @props uplist 上传列表
 * @props action 上传地址
 * @props headers 请求头
 * @props formdata 上传参数
 * @props mime 文件类型
 * @props maxsize 文件大小
 * @props maxnum 最大上传数量
 * @props disabled 是否禁用
 * @props autoupload 是否自动上传
 * @props material 在线文件列表
 * @props options 配置项
 * @props   options.fit 图片裁剪方式
 * @props   options.width 图片宽度
 * @props   options.height 图片高度
 * @props   options.notwatch 是否不监听变化
 * @props   options.other 列表非纯图模式
 * @props   options.sendEdit 替换修改事件
 * @props   options.upDisable 上传按钮是否禁用
 * @props   options.online 选择在线文件
 * @event onChange 上传文件改变事件
 * @event onComplete 上传完成事件
 * @event editorimg 图片插入编辑器事件
 * @event delfile 删除图片事件
 * @example
 * // 默认上传：
 * <mode-upimg :uplist="list" :options="{width: 200, height: 200}" :action="uploadUrl"/>
 * // 选择在线文件：
 * <mode-upimg :uplist="list" :options="{online:true}" :material="material"/>
 * // 替换内置选择器的方式：
 * <mode-upimg :uplist="list" :options="{online:true}">
        <template v-slot:filepopup="modeParams"><materialTemp :modeParams="modeParams" @tohost="默认使用modeParams处理选择，如果需要外部处理选择可使用tohost" /></template>
   </mode-upimg>
 * // 对于在父级呈现选择器的，开启发送修改事件：
 * <mode-upimg :uplist="list" :options="{online:true, sendEdit:Function}" :material="material" />
 */
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { loginOpen } from "@/js/store.js";
import { dragList } from "@/js/function.js";

const emits = defineEmits(['onChange','onComplete','editorimg','delfile']);
function onComplete(data) {
    emits('onComplete', data);
}

const props = defineProps({
    uplist: {
        type: Array
    },
    action: {
        type: String,
        default: ''
    },
    headers: {
        type: Object,
        default: () => ({
            Authorization: 'Bearer ' + loginOpen.getToken()
        })
    },
    formdata: {
        type: Object,
        default: () => ({})
    },
    mime: {
        type: String,
        default: "image/jpeg,image/png,image/gif"
    },
    maxsize: {
        type: Number,
        default: 1024
    },
    maxnum: {
        type: Number,
        default: 20
    },
    disabled: {
        type: Boolean,
        default: false
    },
    autoupload: {
        type: Boolean,
        default: true
    },
    material: {
        type: Array
    },
    options: {
        type: Object,
        default: () => ({fit:'',width:140,height:140,notwatch:false,other:false,sendEdit:null})
    }
})

const upload =ref();
const upfiles = ref(props.uplist)
const piclist = ref([]);
var upStart = false
const isEdit = ref(-1);
// const emit = defineEmits(['update:value'])
//监听变化
watch(() => props.uplist, (newVal, oldValue) => {
    if (newVal && !props.options.notwatch) {
        upfiles.value = newVal;
    }
})

defineExpose({
    upload,closeDialog,isEdit,maxnum:props.maxnum
});

function dragRemove(index) {//删除文件
    // delfile && delfile(index, list)
    upfiles.value.splice(index, 1);
    isEdit.value = -1;
    ElMessage({ message: '移除成功', type: 'success' })
    emits('delfile', index, upfiles.value);
}
function copyUrl(index, list) {//复制地址
    copyText(window.location.protocol + '//' + window.location.host + list[index]);
    ElMessage({ message: '图片地址复制成功', type: 'success' })
}
function editorImg(index, list) {
    emits('editorimg', list[index]);
}

function handleRemove(file, fileList) {//删除文件
    console.log(file, fileList)
}
function beforeRemove(file, fileList) {
    return this.$confirm(`Cancel the transfert of ${file.name} ?`)
}

function handleDownload(file) {
    console.log(file);
}
function handleBefore(file, value, size, maxnum) {
    if(upStart){
        ElMessage({ message: '正在上传中...', type: 'warning' })
        return;
    }
    if (value.length >= maxnum && isEdit.value == -1) {
        ElMessage({ message: `图片数量限制${maxnum}个`, type: 'warning' })
        return false;
    }
    if (file.size / 1024 > size) {
        ElMessage({ message: '图片大小限制' + (size >= 1024 ? (size / 1024) + 'MB' : size + 'KB'), type: 'warning' })
        return false;
    }
    upStart = true;
    // this.newForms[index].toup=false;
}
function handlePictureCardPreview(file) {//开始上传
    // this.dialogImageUrl = file.url
    // this.dialogVisible = true
}
function handleUpSuccess(response, file, fileList, value) {//上传完成
    upload.value?.clearFiles()
    //{name,url,id,sort}
    var data = response.data;
    data.sort = value.length+1;
    data.name = file.name;
    if(isEdit.value == -1){
        value.push(data);
    }else{
        value[isEdit.value].url = response.data.url;
    }
    piclist.value = value.map(item => item.url);
    onComplete(data)
    upStart = false;
    isEdit.value = -1;
}
function handleError(err) {//上传失败
    upload.value?.clearFiles()
    ElMessage.error({ message: '上传失败！' })
    upStart = false;
}
function handleExceed(files, fileList, maxnum) {
    ElMessage.error({ message: `文件数量限制${maxnum}个，当前文件数： ${fileList.length} 个` })
}

function handleChange(file, files) {
    emits('onChange', file, files, isEdit.value);
}


const onUpload = ref()
function onEdit(index) {
    if(isEdit.value==-1){
        isEdit.value = index;
        if(props.options.online){
            fileDialog.value = true;
            return;
        }
        if(props.options.sendEdit){
            //拦截上传在父级做修改操作
            props.options.sendEdit(index, upfiles.value)
            return;
        }
        onUpload.value.click()
    }else{
        isEdit.value = -1;
    }
    
}

function isImageUrl(url) {
    const imageExtensions = /\.(jpg|jpeg|png|gif|webp)$/i;
    return imageExtensions.test(url);
}


//在线图片选择

const fileDialog = ref(false);
function onSelect(item, eve) {
    //{name,url,id,sort}
    var data = item;
    data.sort = upfiles.value.length+1;
    if(isEdit.value>-1){
        upfiles.value[isEdit.value] = data;
        isEdit.value = -1;
    }else if(upfiles.value.length+1<= props.maxnum){
        upfiles.value.push(data);
    }else{
        ElMessage.warning({ message: `文件数量限制${props.maxnum}个` })
    }
    fileDialog.value = false;
}
function closeDialog(){
    fileDialog.value = false;
}


</script>

<style scoped>
.drag-move {
	transition: all .3s ease;
    cursor: move;
}

h3{
    margin: 0;padding: 0 0.5em;width: 100%;background-color: rgba(255, 255, 255, 0.5);color: black;
    font-size: 12px;line-height: 1.4;max-height: 32px;
    position: absolute;left: 0;bottom: 0; overflow: hidden;
}
.editli{border-color: red;}
.editli .editbtn{background-color: red;}
.el-upload__text{min-width: 150px;}
.uploadbtn> .btn svg{height: 15px;vertical-align: -2px;}
.uploader :deep(.el-upload-dragger) {
  padding: 5px 15px;
}
li:hover,li.active{border-color:dodgerblue;box-shadow:rgba(30,143,255,0.3) 0px 10px 12px -6px;}
.img-item{width: 100%;height: 100%;}
.file{width: 100%;}
.file h3{position: static;margin-top: -4px;}
.file .img-item,.file svg{width: 30px;height: 30px;margin: 4px 4px 0;}


.xuanlist{
    display: flex;
    align-items: center;
    justify-content: flex-start;
    flex-wrap:wrap;
    width: 100%;
}
.xuanlist h4{
    display: block; margin: 5px 10px 0;padding: 0;
    font-size: 13px; line-height: 1.4;max-height: 22px;overflow: hidden;
}
.xuanlist span{float: right;font-size: 12px; line-height: 1;color: #999; }
/* 列表样式 */
.list-style {
    list-style-type: none;
    padding: 0;
}
.list-style li {
    width: 100%;
    padding: 5px;
    line-height: 1.5;
    border-bottom: 1px solid #ddd;
    cursor: pointer;
}
.list-style .img{display: none;}
.list-style h4{display: inline-block;}
.list-style li:hover,.list-style li.active{background-color: #f2f2f2;border-color: dodgerblue;}
.list-style li img{max-width: 80px;height: 40px;}

/* 缩略图样式 */
.thumbnail-style {
    list-style-type: none;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
}
.thumbnail-style li {
    margin: 0 10px 38px;
    width: 100px;
    height: 100px;
    background-color: #f2f2f2;
    border: 2px solid #ddd;
}
.thumbnail-style li:hover,.thumbnail-style li.active{box-shadow: rgba(0, 0, 0, 0.2) 0 4px 12px;border-color: dodgerblue;}
.thumbnail-style li .img{width: 100%;height: 100%;overflow: hidden;}
.thumbnail-style li img{width: 100%;height: 100%;}
.xuanbtn{margin: 0 8px 8px 0;padding: 5px 20px;border: #ddd 1px dashed;border-radius: 6px; cursor: pointer;}
</style>
<style>
.uploadbtn {
    position: absolute;
    right: 0;
    top: 0;
    text-align: right;
    height: 0;
    display: flex;
	flex-direction:row-reverse;
	flex-wrap:wrap;/*换行*/
}
.uploadbtn> div {
    font-size: 12px;
    line-height: 20px;
    margin: 3px 2px;
}
.uploadbtn> .btn{
    cursor: pointer;
    text-align: center;
    padding: 0 5px;
    color: white;
    background-color: rgba(0, 0, 0, 0.5);
    border-radius: 2px;
}
</style>